#include "imtPublic.h"
#include "imtActionExecuter.h"
#include "imtAction.h"
#include "imtActionManager.h"

namespace iMate {

	ActionExecuter::ActionExecuter()
	{
		bzero(mIdleActions, sizeof(mIdleActions));
		bzero(mCurrActions, sizeof(mCurrActions));
	}
	ActionExecuter::~ActionExecuter()
	{
		clearAllActions();
	}

	void ActionExecuter::update(Real timeElapsed)
	{
		for (size_t i=0; i<ActionListCount; ++i)
		{
			runActionList(timeElapsed, i);
		}
	}
	void ActionExecuter::runActionList(Real timeElapsed, size_t listIdx/* =ALI_NormalAction*/)
	{
		assert(listIdx < ActionListCount);

		IAction* curAction = getCurrentAction(listIdx);
		if (curAction)
		{
			if (curAction->isOver() )
			{
				moveToNextAction();
			}
			else
			{
				curAction->run(timeElapsed);
			}
		}
	}
	void ActionExecuter::moveToNextAction(size_t listIdx/* =ALI_NormalAction*/)
	{
		IAction* curAction = getCurrentAction(listIdx);
		if (curAction == mIdleActions[listIdx])
		{
			if (mActionLists[listIdx].empty())
			{
				//do nothing 
			}
			else
			{
				if (curAction)
				{
					curAction->terminate();
					curAction = 0;
				}
				curAction = mActionLists[listIdx].front();
				curAction->enter();
			}
		}
		else
		{
			if (!mActionLists[listIdx].empty())
			{
				if (curAction == mActionLists[listIdx].front())
				{
					mActionLists[listIdx].pop_front();
					ActionManager::getSingleton().destroyAction(curAction);
				}
				curAction = 0;
				if (!mActionLists[listIdx].empty())
				{
					curAction = mActionLists[listIdx].front();
					mActionLists[listIdx].pop_front();
					curAction->enter();
				}
			}
			else
			{
			//if (!curAction)
			//{
				curAction = mIdleActions[listIdx];
				curAction->enter();
			//}
			}
		}

		mCurrActions[listIdx] = curAction;
		if (curAction)
		{
			curAction->activate();
		}
	}

	IAction* ActionExecuter::getCurrentAction(size_t listIdx/* =ALI_NormalAction*/) const
	{
		assert(listIdx < ActionListCount);
		
		return mCurrActions[listIdx];
	}

	IAction* ActionExecuter::getCurrentUnIdleAction(size_t listIdx/* =ALI_NormalAction*/) const
	{
		assert(listIdx < ActionListCount);
		
		if (mCurrActions[listIdx] == mIdleActions[listIdx])
		{
			return 0;
		}
		return mCurrActions[listIdx];
	}

	void ActionExecuter::addAction(IAction* action, size_t listIdx/* =ALI_NormalAction*/)
	{
		assert(listIdx < ActionListCount);
		assert(action);

		if (mCurrActions[listIdx] && mCurrActions[listIdx] == mIdleActions[listIdx])
		{
			mCurrActions[listIdx]->stop();
			mCurrActions[listIdx] = action;
			action->enter();
		}
		else if( mCurrActions[listIdx] == NULL )
		{
			mCurrActions[listIdx] = action;
			action->enter();
		}
		else
		{
			mActionLists[listIdx].push_back(action);
		}
		
	}

	void ActionExecuter::setDefaultIdleAction(IAction* action, size_t listIdx/* =ALI_NormalAction*/)
	{
		assert(listIdx < ActionListCount);

		if (mCurrActions[listIdx] == mIdleActions[listIdx])
		{
			mCurrActions[listIdx] = 0;
		}
		ActionManager::getSingleton().destroyAction(mIdleActions[listIdx]);
		mIdleActions[listIdx] = action;
		if (action)
		{
			action->enter();
		}
	}
	void ActionExecuter::clearAllDefaultIdleActions()
	{
		for (size_t i=0; i<ActionListCount; ++i)
		{
			setDefaultIdleAction(NULL, i);
		}
	}

	void ActionExecuter::stopActionList(size_t listIdx/* =ALI_NormalAction*/)
	{
		assert(listIdx < ActionListCount);

		if (mCurrActions[listIdx])
		{
			mCurrActions[listIdx]->stop();
		}

		ActionList::iterator it = mActionLists[listIdx].begin();
		ActionList::iterator end = mActionLists[listIdx].end();
		if (it != end)
		{
			if (*it == mCurrActions[listIdx])
			{
				++it;
			}
			for(ActionList::iterator ite = it; ite != end; ++ite)
			{
				ActionManager::getSingleton().destroyAction(*ite);
			}
			mActionLists[listIdx].erase(it, end);
		}
	}

	void ActionExecuter::stopAllActionLists()
	{
		for (size_t i=0; i<ActionListCount; ++i)
		{
			stopActionList(i);
		}
	}

	void ActionExecuter::clearActionList(size_t listIdx/* =ALI_NormalAction*/)
	{
		assert(listIdx < ActionListCount);

		if (mCurrActions[listIdx] != mIdleActions[listIdx])
		{
			mCurrActions[listIdx] = 0;
		}
		ActionList::iterator it = mActionLists[listIdx].begin();
		ActionList::iterator end = mActionLists[listIdx].end();
		for(; it != end; ++it)
		{
			ActionManager::getSingleton().destroyAction(*it);
		}
		mActionLists[listIdx].clear();
	}

	void ActionExecuter::clearAllActionLists()
	{
		for (size_t i=0; i<ActionListCount; ++i)
		{
			clearActionList(i);
		}
	}

	void ActionExecuter::clearAllActions()
	{
		clearAllActionLists();
		clearAllDefaultIdleActions();
	}


}//iMate